#include <io\jpgstream.h>

void local_error_exit (jpeg_common_struct* cinfo)
{
  char msg[1024];
  sprintf_s(msg, 1024, "error_exit: %d", cinfo->err->msg_code);
}

void local_emit_message (jpeg_common_struct* cinfo, int msg_level)
{
  return;
}

void local_output_message (jpeg_common_struct* /*cinfo*/)
{
  return;
}

bool 
jpgstream::initializeInput(FILE *input) {
  dinfo.err = jpeg_std_error(&jerr);
  jerr.error_exit     = local_error_exit;
  jerr.emit_message   = local_emit_message;
  jerr.output_message = local_output_message;

  jpeg_create_decompress(&dinfo);

  jpeg_stdio_src(&dinfo, input);

  jpeg_read_header(&dinfo, TRUE);

  jpeg_start_decompress(&dinfo);

  jpgheader.width = dinfo.image_width;
  jpgheader.height = dinfo.image_height;
  jpgheader.nc = dinfo.num_components;

  return true;
};

unsigned char *
jpgstream::readLine() {
  if (dinfo.output_scanline < dinfo.output_height) {
    const unsigned int stride = dinfo.num_components * dinfo.image_width;
    unsigned char *row = new unsigned char[stride];
    jpeg_read_scanlines(&dinfo, (JSAMPARRAY)(&row), 1);

    row_index++;

    return row;
  }
  else return NULL;
};

void 
jpgstream::finishInput() {
  jpeg_finish_decompress(&dinfo);
  jpeg_destroy_decompress(&dinfo);
};

bool 
jpgstream::initializeOutput(FILE *output_file, int width, int height, int nc, int scale_num, int scale_denom) {
  cinfo.err = jpeg_std_error(&jerr);
  jpeg_create_compress(&cinfo);

  jpeg_stdio_dest(&cinfo, output_file);

  cinfo.image_width      = width;
  cinfo.image_height     = height;
  cinfo.input_components = nc; //3

  if (nc == 1) {
    cinfo.in_color_space   = JCS_GRAYSCALE;
  }
  else {
    cinfo.in_color_space   = JCS_RGB;
  }

  jpeg_set_defaults(&cinfo);

  cinfo.scale_num = scale_num;
  cinfo.scale_denom = scale_denom;

  jpeg_set_quality (&cinfo, 100, true);
  jpeg_start_compress(&cinfo, true);

  return true;
};

void 
jpgstream::write(unsigned char **data) {
  JSAMPROW row_pointer;
   while (cinfo.next_scanline < cinfo.image_height) {
     //const unsigned int stride = cinfo.next_scanline * cinfo.num_components * cinfo.image_width;
     row_pointer = (JSAMPROW) data[cinfo.next_scanline];
     jpeg_write_scanlines(&cinfo, &row_pointer, 1);
  }
};

void 
jpgstream::finishOutput() {
  jpeg_finish_compress(&cinfo);
  jpeg_destroy_compress(&cinfo);
};

bool 
jpgstream::hasNext() {
  return (dinfo.output_scanline < dinfo.output_height);
};